var util = require("util");
var events = require("events");
var amqCon = require('../util/AMQConnection');
var amqCh = require('../util/AMQChannel');
var log4js = require('log4js');
var logger = log4js.getLogger('Table');
var uuid = require('uuid');

function Table(name, config) {
    logger.trace("enter constructor");
    events.EventEmitter.call(this);
    this.config = config;
    this.name = name;
    this.players = [];
    this.addedAI = false;
    this.key = uuid.v4();
    this.keyT = uuid.v4();
    this.id = uuid.v1();
    this.on('data', Table.processData);
}

util.inherits(Table, events.EventEmitter);

module.exports = Table;

Table.Table = Table;

Table.init = function (cb) {
    logger.trace('enter init');
    var that = this;
    this.amqCon = amqCon.getInstance();
    that.chReceive = new amqCh.AMQChannel(that.amqCon);
    that.chReceive.createExchange(that.config.tables.exchange, that.key, function (obj2) {
        if (obj2 === true) {
            logger.debug('exchange ok, bind queue to this exchange');
            that.chReceive.bindQueue('', null, function (msg) {
                that.emit('data', JSON.parse(msg.content.toString()), that);
            }, true, function (obj3) {
                if (obj3 === true) {
                    logger.debug('bind ok');
                    that.chTable = new amqCh.AMQChannel(that.amqCon);
                    that.chTable.createExchange(that.config.tables.exchange, that.keyT, function (obj4) {
                        if (obj4 === true) {
                            logger.debug('transmit channel ok');
                            cb(true, that.key);
                        } else {
                            logger.error('cannot create transmit channel');
                            logger.error(obj4);
                            cb(obj4);
                        }
                    });
                } else {
                    logger.error('cannot bind queue');
                    logger.error(obj3);
                    cb(obj3);
                }
            });
        } else {
            logger.error('cannot create exchange');
            logger.error(obj2);
            cb(obj2);
        }
    });
};

Table.processData = function (data, that) {
    logger.trace('enter processData');
    switch (data.action) {
        case 'join_table':
            var player = {};
            player.name = data.player;
            player.key = data.key;
            player.type = data.type;
            player.chPlayer = new amqCh.AMQChannel(that.amqCon);
            player.chPlayer.createExchange(that.config.players.exchange, player.key, function (obj4) {
                if (obj4 === true) {
                    logger.info('created channel to player: ' + player.name);
                    that.players.push(player);
                    player.chPlayer.sendMessage({
                        action: 'join_table',
                        table: that.name,
                        tableGroupKey: that.keyT
                    });
                    that.requestAI();
                    that.startGame();
                } else {
                    logger.error('cannot create channel to player: ' + player.name);
                    logger.error(obj4);
                    // fatal error, need to retry
                }
            });
            break;

        case 'disconnect':
            that.chTable.sendMessage({
                action: 'destroy'
            });
            that.sendDestroyMessage();
            break;

        default:
            logger.debug('cannot process action: ' + data.action);
            break;
    }
};

Table.prototype.requestAI = function () {
    logger.trace('enter requestAI');
    var that = this;
    if (!this.addedAI) {
        if (this.players.filter(function (el) {
                return (el.type === 'user');
            }).length === this.config.tables.maxUsers) {
            logger.info('send request to create ai users');
            this.chPlayerManager = new amqCh.AMQChannel(this.amqCon);
            this.chPlayerManager.createExchange(this.config.playerManager.exchange, this.config.playerManager.key, function (obj4) {
                if (obj4 === true) {
                    that.chPlayerManager.sendMessage({
                        action: 'find_player',
                        table: that.name,
                        tableKey: that.key,
                        from: that.config.tables.maxUsers,
                        total: that.config.tables.maxPlayers - that.config.tables.maxUsers
                    });
                    that.addedAI = true;
                } else {
                    logger.error('cannot create channel to playerManager');
                    logger.error(obj4);
                    // fatal error, need to retry
                }
            });
        }
    }
};

Table.prototype.startGame = function () {
    logger.trace('enter startGame');
    var that = this;
    // if table is full, start the game
    if (that.players.length === that.config.tables.maxPlayers) {
        logger.info('table is full, start the game');
        // just select the first player, need to be reimplemented in sub class
        that.next = 0;
        that.players[0].chPlayer.sendMessage({
            action: 'start',
            next: that.players[0].name
        });
    }
};

Table.prototype.sendDestroyMessage = function () {
    logger.trace('enter sendDestroyMessage');
    var that = this;
    var ch = new amqCh.AMQChannel(that.amqCon);
    ch.createExchange(that.config.tableManager.exchange, that.config.tableManager.key, function (obj4) {
        if (obj4 === true) {
            logger.debug('transmit channel ok');
            ch.sendMessage({
                action: 'delete_table',
                tableID: that.id
            });
        } else {
            logger.error('cannot create transmit channel');
            logger.error(obj4);
        }
    });
};
